package controller;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.util.Date;

import dataStructure.LinkedList;
import entity.Member;
import entity.MemberInfo;
import entity.RedemptionRecord;
import entity.Staff;

public class MemberController extends ProgramFlowControl {
	private LinkedList<Member> memberList;
	private LinkedList<RedemptionRecord> redemptionRecords;
	private Staff staff;
	
	public MemberController(LinkedList<Member> membersList, LinkedList<RedemptionRecord> redemptionRecords, Staff staff) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
		super("Members Management");

		this.setMemberList(membersList);
		this.setRedemptionRecords(redemptionRecords);
		this.staff =staff;

		// Pushing options to ProgramFlowControl first;
		this.addNewChoice("1", "1. Add New Member", this, "addNewMemberAction");
		this.addNewChoice("2", "2. Suspends Member", this, "suspendMemberAction");
		this.addNewChoice("3", "3. Gift Redemption", this, "giftRedemptionAction");
		this.addNewChoice("4", "4. Check Information", this, "checkMemberInformationAction");
		this.addNewChoice("5", "5. Top up balance", this, "topUpBalanceAction");
		this.setTeminateOption("x", "Press x to return to Main Menu", this, "clearUp");
	}

	public void addNewMemberAction() throws IOException, NumberFormatException, SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchFieldException, ParseException {
		String hkID, firstName, lastName, contactADDR, gender;
		Date birthDay;
		int contactNo;

		System.out.println("Please fill up the following information: (Input -1 to stop filling)");

		hkID = UserInputControl.getStrInput("HKID[E.g: A1234567]: ", "[A-Z]{1}[0-9]{7}");
		if (hkID != null) {
			lastName = UserInputControl.getStrInput("Last name: ", "^[a-zA-Z]+$");
			if (lastName != null) {
				firstName = UserInputControl.getStrInput("First name[TaiMan, no spacing]: ", "^[a-zA-Z]+$");
				if (firstName != null) {
					contactADDR = UserInputControl.getStrInput("Contact Address: ", ".{1,}");
					if (contactADDR != null) {
						gender = UserInputControl.getStrInput("Gender[M/F]: ", "[M|F]{1}");
						if (gender != null) {
							birthDay = UserInputControl.getDateInput("Date of birth[yyyy-mm-dd]: ");
							if (birthDay != null) {
								contactNo = UserInputControl.getIntInput("Contact phone number: ", "8");
								if (contactNo != 0) {
									String memberID =this.getNewID(this.memberList);
									this.addNewMember(hkID, lastName, firstName, birthDay, contactADDR, contactNo, gender, memberID, new Date(), 0, 0, "true");
									System.out.println("New Member added, Member ID is: " + memberID);
								}
							}
						}
					}
				}
			}
		}
	}

	private String getNewID(LinkedList<?> list) {
		String temp = Integer.toString(list.getLength() + 1);
		int length= temp.length();

		String newID = "";
		for (int i = 0; i < 6 - length; i++) {
			newID+="0";
		}
		return newID.concat(temp);
	}

	public void addNewMember(String hkID, String lastName, String firstName, Date birthDay, String contactADDR, int contactNo, String gender, String memberID, Date admissionDate, int giftPoint, float balance, String status) throws SecurityException,
			IllegalArgumentException, NoSuchFieldException, IllegalAccessException, ParseException {

		this.getMemberList().addContent(new Member(hkID, lastName, firstName, birthDay, contactADDR, contactNo, gender, memberID, admissionDate, giftPoint, balance, status));
	}

	public void suspendMemberAction() throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NullPointerException, ParseException {
		String memberID = UserInputControl.getStrInput("Suspend Member: ", "[0-9]{6}");

		if (memberID != null) {
			if (this.suspendMember(memberID)) {
				System.out.println("Member ID " + memberID + " is suspended.");
			} else {
				this.printNoMemberFound();
			}
		}
	}

	public boolean suspendMember(String memberID) throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NullPointerException, ParseException {
		if (memberID != null) {
			Member suspendMember = this.searchMember(memberID);
			if (suspendMember != null) {
				suspendMember.getMemberInfo().setStatus(false);
				return true;
			}
		}
		return false;
	}

	public void giftRedemptionAction() throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NullPointerException, ParseException {
		String input = UserInputControl.getStrInput("Member ID: ", "[0-9]{6}");
		if (input != null) {
			Member result = this.searchMember(input);
			if (result != null) {
				int giftPoint = result.getMemberInfo().getGiftPoint();
				System.out.println("Gift Point Balance: " + giftPoint);

				if (giftPoint >= 50) {
					this.giftRedemption(result);
				} else
					System.out.println("Gift Point is insufficient to redempt.");
			} else
				this.printNoMemberFound();
		}
	}

	public void giftRedemption(Member member) throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NullPointerException, ParseException {
		if (member != null && member.getMemberInfo().isStatus()) {
			int giftPoint = member.getMemberInfo().getGiftPoint();
			int maxNo2Exchange = giftPoint / 50;
			int nCoupon = UserInputControl.getIntInput("Enter the No. of coupons to exhange (0.." + maxNo2Exchange + "): ", "0,");// Change get int to restrict to a range rather than a length?
			if (nCoupon < 0 || nCoupon > maxNo2Exchange)
				System.out.println("Invalid input");
			else {
				member.getMemberInfo().setGiftPoint(giftPoint - nCoupon * 50);
				String msg = (nCoupon > 1) ? nCoupon + " coupon is given." : nCoupon + " coupons is given.";
				System.out.print(msg);
				
				String newRecordID = this.getNewID(this.redemptionRecords);
				this.redemptionRecords.addContent(new RedemptionRecord(newRecordID, new Date(), this.staff.getStaffName(), (String) member.getAttrVal("id"), nCoupon, nCoupon * 50));
			}
		} else {
			System.out.println("MemberID: " + member.getMemberInfo().getId() + " not found or suspended.");
		}
	}
	
	private void printNoMemberFound() {
		System.out.println("No Member Found.");
	}

	public void checkMemberInformationAction() throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, ParseException {
		System.out.println("Check Member Information");
		String input = UserInputControl.getStrInput("Member ID: ", "[0-9]{6}");
		if (input != null) {
			Member result = this.searchMember(input);
			if (result != null)
				result.printContent();
			else
				this.printNoMemberFound();
		}
	}
	
	public void topUpBalanceAction() throws IOException, SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, ParseException{
		System.out.println("Top Up Member Balance");
		String input = UserInputControl.getStrInput("Member ID: ", "[0-9]{6}");
		if (input != null) {
			Member result = this.searchMember(input);
			if (result != null){
				System.out.println("Current Balance: "+ result.getMemberInfo().getBalance() + "\n");
				
				int topUpVal = UserInputControl.getIntInput("Enter top up value: ", "0,");
				MemberInfo mInfo = result.getMemberInfo();
				
				mInfo.setBalance(topUpVal+mInfo.getBalance());
				System.out.println("New Balance : "+ result.getMemberInfo().getBalance() + "\n");
			} else
				this.printNoMemberFound();
		}
	}

	public Member searchMember(String id) throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, ParseException {
		if (id != null) {
			Member result = this.getMemberList().searchContent("id", id);
			if (result != null)
				return result;
		}
		return null;
	}

	public void begin() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, IOException {
		this.flowControl();
	}

	public void clearUp() {
	}

	public LinkedList<Member> getMemberList() {
		return memberList;
	}

	public void setMemberList(LinkedList<Member> memberList) {
		this.memberList = memberList;
	}

	public LinkedList<RedemptionRecord> getRedemptionRecords() {
		return redemptionRecords;
	}

	public void setRedemptionRecords(LinkedList<RedemptionRecord> redemptionRecords) {
		this.redemptionRecords = redemptionRecords;
	}
}